﻿using System;
using System.Data.Linq;
using System.Linq;
using CoreLibrary.Cache;
using CoreLibrary.Repo;
using CoreLibrary.Security;
using IBBI.DataBase.Obj;
using IBBI.DataBase.Persistent;
 
namespace IBBI.DataBase.Impl {

    public class UserService : BaseRepository<User>, IUserService {

        private static readonly Func<DataContext, int, User> 
            LinqGetAccountById = CompiledQuery.Compile((DataContext context, int userId) => 
                context.GetTable<User>().SingleOrDefault(account => account.Id == userId));

        private static readonly Func<DataContext, string, User>
            LinqGetAccountByEmail = CompiledQuery.Compile((DataContext context, string email) =>
                context.GetTable<User>().SingleOrDefault(account => account.Email.Equals(email)));

        public ICache Cache { get; set; }

        public override string TableName {
            get { return "IBBI_USERS"; }
        }

        public void UpdateUserAccount(UpdateUserRequest updateUserRequest) {
            
        }

        public User GetUserById(int accountId) {
            return Execute(context => LinqGetAccountById(context, accountId));
        }

        public User GetUserByEmail(string email) {
            return Execute(context => LinqGetAccountByEmail(context, email));
        }

        public AuthenticateResponse Authenticate(AuthenticateRequest request) {
            return Execute(context => {
                var account = LinqGetAccountByEmail(context, request.Email);
                if (account == null) {
                    return new AuthenticateResponse {
                        Authenticated = false,
                        Message = "Account doesn't exist.",
                        User = null
                    };
                }

                if (!account.Password.Equals(Hasher.SHA256Hex(request.Password))) {
                    return new AuthenticateResponse {
                        Authenticated = false,
                        Message = "Password doesn't match",
                        User = null
                    };
                }

                if (!account.Enabled) {
                    return new AuthenticateResponse {
                        Authenticated = false,
                        Message = "This Account is not enabled.",
                        User = null
                    };
                }

                return new AuthenticateResponse {
                       Authenticated = true,
                       User          = account,
                       Message       = string.Empty
                };    
            });
        }

        public void CreateUserAccount(CreateUserRequest request) {
            Execute((context, ts) => {
                var account = request.Build();

                var accByEmail = LinqGetAccountByEmail(context, account.Email);
                if (accByEmail != null) {
                    throw new ArgumentException(account.Email + " already exists.");
                }

                context.GetTable<User>().InsertOnSubmit(account);
                context.SubmitChanges();
                ts.Complete();
            });
        }
        
    }
}